home *** CD-ROM | disk | FTP | other *** search
- //
- // Finger Version 3.1, a Windows Sockets Finger Client
- //
- // Copyright 1992, 1993 Network Research Corporation
- //
- // Permission to use, modify, and distribute this software and its
- // documentation for any purpose and without fee is hereby granted, provided
- // that the above copyright notice appears in all copies and that both
- // that copyright notice and this permission notice appear in supporting
- // documentation. NRC makes no claims as to the suitability of this software
- // for any purpose.
- //
- // Module NETWRKM uses Windows Sockets asynchronous (message based) calls to
- // query a remote finger server for a list of currently logged in users.
- // Module FINGER initiates the operation by calling FingerStart(), and
- // NETWRKM signals completion by calling FingerFinish(). NETWRKM uses DSPLIST
- // functions to send the retrieved data to the FINGER user interface module.
- //
- // 04/01/92 Lee Murach Created.
- // 11/30/92 Lee Murach Adapted for WS 1.1 WSAAsyncSelect()
- // 12/02/92 Lee Murach Restructured for Finger 3.0 integrated release
- // 01/15/92 Lee Murach Change FD_READ to FD_READ | FD_CLOSE
- // 03/01/93 Lee Murach Added WSAEWOULDBLOCK check to DoConnect()
- // 03/25/93 Lee Murach Added per-user finger support.
- //
-
- #include <memory.h>
- #include <string.h>
- #include <windows.h>
- #include <winsock.h>
- #include "finger.h"
-
- // messages for windows sockets returns
- #define WM_SERVICE (WM_USER + 1)
- #define WM_HOSTRESOLVED (WM_USER + 2)
- #define WM_CONNECTED (WM_USER + 3)
- #define WM_OKTORECV (WM_USER + 4)
- #define NETWINDOW "NetWindow"
-
- LONG FAR APIENTRY NetWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
- LONG DoResolveHost(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
- LONG DoConnect(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
- LONG DoQuery(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
- LONG DoRetrieval(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
- void LoadEntBuf(IPA ipa);
-
- DECODEWORD netMsgs[] = // network window messages & handlers
- {
- WM_SERVICE, DoResolveHost,
- WM_HOSTRESOLVED, DoConnect,
- WM_CONNECTED, DoQuery,
- WM_OKTORECV, DoRetrieval
- };
-
- SOCKET Sock; // connects to remote server's socket
- int Port; // hold port for finger service
- char EntBuf[MAXGETHOSTSTRUCT]; // buf for service & resolve returns
- HWND hNetWnd; // network window handle
-
- //
- // InitNetApp -- registers window class for the network module's invisible
- // child window. This is called only for the first instance of finger.
- //
- VOID InitNetApp(VOID)
- {
- WNDCLASS wndclass;
-
- wndclass.style = 0;
- wndclass.lpfnWndProc = NetWndProc;
- wndclass.cbClsExtra = 0;
- wndclass.cbWndExtra = 0;
- wndclass.hInstance = hInst;
- wndclass.hIcon = 0;
- wndclass.hCursor = 0;
- wndclass.hbrBackground = 0;
- wndclass.lpszMenuName = NULL;
- wndclass.lpszClassName = NETWINDOW;
-
- RegisterClass(&wndclass);
- }
-
- //
- // InitNetInst -- initializes the network module by creating an invisible
- // child of the main finger window which will be used to receive Windows
- // Sockets notification messages. The window will be automatically
- // destroyed when the main window exits, so no finalization is required.
- //
- VOID InitNetInst(HWND hWnd)
- {
- hNetWnd = CreateWindow( NETWINDOW, "", WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT,
- CW_USEDEFAULT, CW_USEDEFAULT,
- hWnd, 0, hInst, NULL);
- }
-
- //
- // NetWndProc -- callback function for network window. The network window
- // is a child window created especially to receive windows sockets network
- // messages. The function decodes and routes to appropriate message handler.
- //
- LONG FAR APIENTRY NetWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
- {
- int i;
-
- for (i = 0; i < dim(netMsgs); i++)
- {
- if (wMsg == netMsgs[i].Code)
- return((*netMsgs[i].Fxn)(hWnd, wMsg, wParam, lParam));
- }
-
- return(DefWindowProc(hWnd, wMsg, wParam, lParam));
- }
-
- //
- // FingerStart -- called by FINGER module to initiate a conversation with
- // the remote finger server. We start by resolving the finger tcp service
- // to a port number. Windows Sockets WSAAsync routines signal completion
- // by posting messages, which are dispatched to appropriate handlers.
- //
- VOID FingerStart(VOID)
- {
- if (WSAAsyncGetServByName(hNetWnd, WM_SERVICE, "finger", "tcp",
- EntBuf, sizeof(EntBuf)) == -1)
- {
- ReportFingerErr(FE_NOPORT);
- FingerFinish(FE_ERROR);
- }
- }
-
- //
- // DoResolveHost -- resolves host specifier to an IP address. Since we
- // allow a "dotted decimal" IP address to be entered in lieu of a DNS host
- // name, we check for this syntax before assuming a DNS name.
- //
- LONG DoResolveHost(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
- {
- IPA ipa;
-
- if (WSAGETSELECTERROR(lParam))
- {
- ReportFingerErr(FE_NOPORT); // cannot locate finger service
- FingerFinish(FE_ERROR);
- return(FALSE);
- }
-
- Port = ((SERVENT *)EntBuf)->s_port; // we're going to reuse the buffer
-
- // if host specifier is dotted decimal ip address, resolve right here
- if ((ipa = INET_ADDR(szHostName)) != INADDR_NONE)
- {
- LoadEntBuf(ipa);
- PostMessage(hNetWnd, WM_HOSTRESOLVED, 0, 0);
- return(FALSE);
- }
-
- // assume specifier is DNS host name
- if (WSAAsyncGetHostByName(hNetWnd, WM_HOSTRESOLVED, szHostName,
- EntBuf, sizeof(EntBuf)) == -1)
- {
- ReportFingerErr(FE_NOHOST);
- FingerFinish(FE_ERROR);
- }
-
- return(FALSE);
- }
-
- //
- // LoadEntBuf -- loads the EntBuf (sufficiently) with a HOSTENT and
- // referenced IPA. This is so we can return IPAs in the same
- // manner as a WSAAsync call.
- //
- void LoadEntBuf(IPA ipa)
- {
- LPHOSTENT phe = (LPHOSTENT) EntBuf;
- LPPIPA ppipa = (LPPIPA) (EntBuf + sizeof(HOSTENT));
- LPIPA pipa = (LPIPA) (EntBuf + sizeof(HOSTENT) + sizeof(LPPIPA));
-
- _fmemset(phe, 0, sizeof(HOSTENT));
- phe->h_addr_list = (char FAR * FAR *) ppipa;
- *ppipa = pipa;
- *pipa = ipa;
- }
-
- //
- // DoConnect -- allocates a socket and connects to remote finger server.
- //
- LONG DoConnect(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
- {
- if (WSAGETSELECTERROR(lParam))
- {
- ReportFingerErr(FE_NOHOST); // could not resolve host name
- FingerFinish(FE_ERROR);
- return(FALSE);
- }
-
- if ((Sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0)
- {
- SOCKADDR_IN server;
- u_long block = FALSE;
- HOSTENT *phe = (HOSTENT *) EntBuf;
-
- memset(&server, 0, sizeof(server));
- server.sin_family = AF_INET;
- server.sin_port = Port;
- server.sin_addr = *((IN_ADDR FAR *) *phe->h_addr_list);
-
- // post message when connect is established
- WSAAsyncSelect(Sock, hNetWnd, WM_CONNECTED, FD_CONNECT);
-
- if ( connect(Sock, (SOCKADDR *)&server, sizeof(server)) < 0 &&
- WSAGetLastError() != WSAEWOULDBLOCK)
- {
- ReportFingerErr(FE_NOCONN);
- FingerFinish(FE_ERROR);
- }
- }
- else
- {
- ReportFingerErr(FE_NOSOCK);
- FingerFinish(FE_ERROR);
- }
-
- return(FALSE);
- }
-
- //
- // DoQuery -- sends a query for all currently logged in users to remote
- // server.
- //
- LONG DoQuery(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
- {
- char msg[MAXUSER+3];
- int msglen;
-
- if (WSAGETSELECTERROR(lParam))
- {
- ReportFingerErr(FE_NOCONN); // could not connect to server
- FingerFinish(FE_ERROR);
- return(FALSE);
- }
-
- // post message when data is available for read
- WSAAsyncSelect(Sock, hNetWnd, WM_OKTORECV, FD_READ | FD_CLOSE);
-
- strcpy(msg, szUser);
- strcat(msg, "\r\n");
- msglen = strlen(msg);
-
- if (send(Sock, msg, msglen, 0) != msglen)
- {
- ReportFingerErr(FE_NOSEND);
- FingerFinish(FE_ERROR);
- return(FALSE);
- }
-
- OpenDisplayList(); // new display list will contain received data
-
- return(FALSE);
- }
-
- //
- // DoRetrieval -- fetches ascii text from remote finger server, and builds
- // display list until the end of the text stream.
- //
- LONG DoRetrieval(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
- {
- static char buf[500];
- int nchars, err = 0;
-
- /* receives data not to exceed buf size & reenables notification
- of more data pending */
-
- if ((nchars = recv(Sock, (char FAR *)&buf, sizeof(buf), 0)) > 0)
- {
- PushChars(buf, nchars); // adds character to display list
- return(FALSE);
- }
-
- CloseDisplayList(); // close list if error or end-of-data
- closesocket(Sock); // don't need socket anymore
-
- if (nchars < 0)
- {
- FreeDisplayList();
- ReportFingerErr(FE_NORECV); // error during receive
- err = FE_ERROR;
- }
-
- FingerFinish(err); // signal end-of-finger
-
- return(FALSE);
- }
-
-